package com.hzeng.util;

import java.awt.Color;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleInsets;

public class MyTimeSeriesChart
{
	
	private static MyTimeSeriesChart myTimeSeriesChart = new MyTimeSeriesChart();
	
	private MyTimeSeriesChart() {
		
	}
	
	public static MyTimeSeriesChart getInstance() {
		if (myTimeSeriesChart == null) {
			myTimeSeriesChart = new MyTimeSeriesChart();
		}
		return myTimeSeriesChart;
	}
	
	
	
	Map<Integer, JFreeChart> charts = new HashMap<Integer, JFreeChart>();
	Map<Integer, TimeSeries> timeSeries = new HashMap<Integer, TimeSeries>();
	
	JFreeChart chart = null;
	TimeSeries tempTimeSeries = null;
	TimeSeriesCollection dataset = null;
	Long pid = null;
	
	boolean startFlag = false;
	
	

	public boolean isStartFlag() {
		return startFlag;
	}

	public void setStartFlag(boolean startFlag) {
		this.startFlag = startFlag;
	}

	public Long getPid() {
		return pid;
	}

	public void setPid(Long pid) {
		this.pid = pid;
	}
	
	public Map<Integer, JFreeChart> createLiveCharts() {
		if (pid == 0l) {
			charts.put(Constants.CHART_SYS_CPU, createSystemLiveChart(Constants._SYS_CPU, Constants._TIME, Constants._SYS_CPU, Constants._SYS_CPU));
			charts.put(Constants.CHART_SYS_MEMORY, createSystemLiveChart(Constants._SYS_MEMORY, Constants._TIME, Constants._SYS_MEMORY, Constants._SYS_MEMORY));
			charts.put(Constants.CHART_SYS_IO, createSystemLiveChart(Constants._SYS_IO, Constants._TIME, Constants._SYS_IO, Constants._SYS_IO));
			
			return charts;
		}else {
			
		}
		Program program = ProgramMonitor.getInstance().getProgramSchema(pid);
		
		charts.put(Constants.CHART_CPU, createLiveChart(program.getName() + "/" + program.getPid(), Constants._TIME, Constants._CPU, program.getName()));
		charts.put(Constants.CHART_MEMORY, createLiveChart(program.getName() + "/" + program.getPid(), Constants._TIME, Constants._MEMORY, program.getName()));
		charts.put(Constants.CHART_VM, createLiveChart(program.getName() + "/" + program.getPid(), Constants._TIME, Constants._VM, program.getName()));
		
		
		return charts;
	}
	
	public JFreeChart createSystemLiveChart(String title,String xLabel,String yLabel,String seriesTitle) {
		TimeSeries tempTimeSeries1 = null;
		TimeSeries tempTimeSeries2 = null;
		
	 	if (yLabel.equals(Constants._SYS_CPU)) {
	 		tempTimeSeries1 = new TimeSeries(seriesTitle);
	 		timeSeries.put(Constants.CHART_SYS_CPU, tempTimeSeries1);
	 		yLabel = yLabel + " (%)";
		}else if (yLabel.equals(Constants._SYS_MEMORY)) {
			tempTimeSeries1 = new TimeSeries(Constants._SYS_MEMORY);
			tempTimeSeries2 = new TimeSeries(Constants._SYS_TOTAL_MEMORY);
			timeSeries.put(Constants.CHART_SYS_MEMORY, tempTimeSeries1);
			timeSeries.put(Constants.CHART_SYS_TOTAL_MEMORY, tempTimeSeries2);
			yLabel = yLabel + " (M)";
		}else if (yLabel.equals(Constants._SYS_IO)) {
			tempTimeSeries1 = new TimeSeries(Constants._SYS_READ);
			tempTimeSeries2 = new TimeSeries(Constants._SYS_WRITE);
			timeSeries.put(Constants.CHART_SYS_READ, tempTimeSeries1);
			timeSeries.put(Constants.CHART_SYS_WRITE, tempTimeSeries2);
			yLabel = yLabel + " (K/S)";
		}
	 	
	 	dataset = new TimeSeriesCollection();
	 	
	 	if (tempTimeSeries1 != null) {
	 		dataset.addSeries(tempTimeSeries1);
	 		tempTimeSeries1 = null;
		}
	 	
	 	if (tempTimeSeries2 != null) {
	 		dataset.addSeries(tempTimeSeries2);
	 		tempTimeSeries2 = null;
		}
		

        chart = ChartFactory.createTimeSeriesChart(
        	title,  // title
        	xLabel,             // x-axis label
        	yLabel,   // y-axis label
            dataset,            // data
            true,               // create legend
            true,               // generate tooltips
            false               // generate URLs
        );

        chart.setBackgroundPaint(Color.white);

        XYPlot plot = (XYPlot) chart.getPlot();
        ValueAxis valueaxis = plot.getDomainAxis();
        valueaxis.setAutoRange(true);
        valueaxis.setFixedAutoRange(300000D);
        
        
        
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        plot.setDomainCrosshairVisible(true);
        plot.setRangeCrosshairVisible(false);
        
        XYItemRenderer r = plot.getRenderer();
        if (r instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
            renderer.setBaseShapesVisible(false);
            renderer.setBaseShapesFilled(false);
        }
        
        DateAxis axis = (DateAxis) plot.getDomainAxis();
        axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss"));
        axis.setTickUnit(new DateTickUnit(DateTickUnitType.MINUTE, 1));
        
        
        return chart;
	}
	
	public JFreeChart createLiveChart(String title,String xLabel,String yLabel,String seriesTitle) {
		 	tempTimeSeries = new TimeSeries(seriesTitle);
		 	if (yLabel.equals(Constants._CPU)) {
		 		timeSeries.put(Constants.CHART_CPU, tempTimeSeries);
		 		yLabel = yLabel + " (%)";
			}else if (yLabel.equals(Constants._MEMORY)) {
				timeSeries.put(Constants.CHART_MEMORY, tempTimeSeries);
				yLabel = yLabel + " (M)";
			}else if (yLabel.equals(Constants._VM)) {
				timeSeries.put(Constants.CHART_VM, tempTimeSeries);
				yLabel = yLabel + " (M)";
			}else if (yLabel.equals(Constants._READ)) {
				timeSeries.put(Constants.CHART_READ, tempTimeSeries);
				yLabel = yLabel + " (K/S)";
			}else if (yLabel.equals(Constants._WRITE)) {
				timeSeries.put(Constants.CHART_WRITE, tempTimeSeries);
				yLabel = yLabel + " (K/S)";
			}
		 	
		 	
			dataset = new TimeSeriesCollection();
			dataset.addSeries(tempTimeSeries);
			tempTimeSeries = null;

	        chart = ChartFactory.createTimeSeriesChart(
	        	title,  // title
	        	xLabel,             // x-axis label
	        	yLabel,   // y-axis label
	            dataset,            // data
	            true,               // create legend
	            true,               // generate tooltips
	            false               // generate URLs
	        );

	        chart.setBackgroundPaint(Color.white);

	        XYPlot plot = (XYPlot) chart.getPlot();
	        ValueAxis valueaxis = plot.getDomainAxis();
	        valueaxis.setAutoRange(true);
	        valueaxis.setFixedAutoRange(300000D);
	        
	        
	        
	        plot.setBackgroundPaint(Color.lightGray);
	        plot.setDomainGridlinePaint(Color.white);
	        plot.setRangeGridlinePaint(Color.white);
	        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
	        plot.setDomainCrosshairVisible(true);
	        plot.setRangeCrosshairVisible(false);
	        
	        XYItemRenderer r = plot.getRenderer();
	        if (r instanceof XYLineAndShapeRenderer) {
	            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
	            renderer.setBaseShapesVisible(false);
	            renderer.setBaseShapesFilled(false);
	        }
	        
	        DateAxis axis = (DateAxis) plot.getDomainAxis();
	        axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss"));
	        axis.setTickUnit(new DateTickUnit(DateTickUnitType.MINUTE, 1));
	        
	        
	        return chart;
	 }
	
    public JFreeChart createLiveChart() {
    	return createLiveChart("3245/chrome CPU","Time","3245 CPU","memory");
    }
    
    public void updateChartData(List<Program> programs) {
    	Program p = null;
    	Program sys = null;
    	if (programs == null || programs.size() < 1) {
			return;
		}
    	for (int i = programs.size() - 1; i >= 0; i--) {
    		sys = programs.get(i);
    		if (sys.getPid() == 0) {
				break;
			}
    		sys = null;
    	}
    	
		if (startFlag) {
			for (int i = programs.size() - 1; i >= 0; i--) {
				p = programs.get(i);
				if (p.getPid() == 0) {
					
				}else {
					//update specify program data
					if (pid != null && pid > 0) {
						TimeSeries cpuSeries = timeSeries.get(Constants.CHART_CPU);
		        		cpuSeries.add(new Second(new Date(p.getTimestamp())), p.getCpu());
		        		
		        		TimeSeries memorySeries = timeSeries.get(Constants.CHART_MEMORY);
		        		memorySeries.add(new Second(new Date(p.getTimestamp())), p.getMemory());
		        		
		        		TimeSeries vmSeries = timeSeries.get(Constants.CHART_VM);
		        		vmSeries.add(new Second(new Date(p.getTimestamp())), p.getVirtualMemory());
					}
				}
			}
		}else {
			
		}
		if (sys != null && sys.getPid() == 0) {
			//update system data
			TimeSeries tempSeries = timeSeries.get(Constants.CHART_SYS_CPU);
    		tempSeries.add(new Second(new Date(sys.getTimestamp())), sys.getCpu());
    		
    		
    		tempSeries = timeSeries.get(Constants.CHART_SYS_MEMORY);
    		tempSeries.add(new Second(new Date(sys.getTimestamp())), sys.getMemory());
    		
    		tempSeries = timeSeries.get(Constants.CHART_SYS_TOTAL_MEMORY);
    		tempSeries.add(new Second(new Date(sys.getTimestamp())), sys.getTotalMemory());
    		
    		tempSeries = timeSeries.get(Constants.CHART_SYS_READ);
    		tempSeries.add(new Second(new Date(sys.getTimestamp())), sys.getRead());
    		
    		tempSeries = timeSeries.get(Constants.CHART_SYS_WRITE);
    		tempSeries.add(new Second(new Date(sys.getTimestamp())), sys.getWrite());
    		tempSeries = null;
		}
			
    }
    
}
